home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- MODULE: recio.c
- PURPOSE: recio primary functions
- COPYRIGHT: (C) 1994 William Pierpoint
- COMPILER: Borland C Version 3.1
- OS: MSDOS Version 6.2
- VERSION: 2.00
- RELEASE: April 15, 1994
- *****************************************************************************/
-
- #include <ctype.h>
- #include <errno.h>
- #include <float.h>
- #include <limits.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "recio.h"
-
- #define rcol(rp) ((rp)->r_colno)
- #define rflags(rp) ((rp)->r_flags)
- #define rfd(rp) ((rp)->r_fd)
- #define rfp(rp) ((rp)->r_fp)
- #define rreclen(rp) ((rp)->r_reclen)
- #define rrecsiz(rp) ((rp)->r_recsiz)
- #define rfldsiz(rp) ((rp)->r_fldsiz)
- #define rfldch(rp) ((rp)->r_fldch)
- #define rtxtch(rp) ((rp)->r_txtch)
-
- /* private module variables */
- static REC *_RECS = NULL; /* ptr to array of REC structures */
-
- static REC rin = { 1, 0, stdin, "stdin", 0L,
- 0, 0, 0, 0, NULL,
- 0, NULL, RECFLDCH, RECTXTCH, RECIN };
-
- static REC rout = { 2, _R_WRT, stdout, "stdout", 0L,
- 0, 0, 0, 0, NULL,
- 0, NULL, RECFLDCH, RECTXTCH, RECOUT };
-
- static REC rerr = { 3, _R_WRT, stderr, "stderr", 0L,
- 0, 0, 0, 0, NULL,
- 0, NULL, RECFLDCH, RECTXTCH, RECERR };
-
- #if defined (__MSDOS__) || (MSDOS)
- static REC rprn = { 4, _R_WRT, stdprn, "stdprn", 0L,
- 0, 0, 0, 0, NULL,
- 0, NULL, RECFLDCH, RECTXTCH, RECPRN };
- #define NREC 4 /* number of static record streams */
- #else
- #define NREC 3
- #endif
- #define ROPEN_MIN NREC /* reserved for recin, etc */
- #define ROPEN max(ROPEN_MAX, ROPEN_MIN)
-
- /* public variables */
- REC *recin = &rin;
- REC *recout = &rout;
- REC *recerr = &rerr;
- #if defined (__MSDOS__) || (MSDOS)
- REC *recprn = &rprn;
- #endif
-
- /* friend variables */
- char _r_nsbuf[NSBUFSIZ]; /* buffer for numeric to string conversions */
-
- /* Support functions */
- /****************************************************************************/
- static void /* returns nothing */
- _rexit( /* at program exit, clean up */
- void) /* no arguments */
- /****************************************************************************/
- {
- /* free recin buffers */
- free(rflds(recin));
- free(rrecs(recin));
- rflds(recin) = NULL;
- rfldsiz(recin) = 0;
- rrecs(recin) = NULL;
- rrecsiz(recin) = 0;
- rreclen(recin) = 0;
-
- /* ensure all record streams closed */
- rcloseall();
- }
-
- /****************************************************************************/
- void /* return error number (0=no error) */
- _rsetexitfn( /* register _rexit function with atexit() */
- REC *rp) /* record pointer */
- /****************************************************************************/
- {
- static int once=0; /* register exit fn only once */
-
- if (!once) {
-
- /* execute this path at most one time */
- once++;
-
- /* if atexit() fails to register _rexit() function */
- if (atexit(_rexit)) {
-
- /* register warning */
- rsetwarn(rp, R_WNOREG);
- }
- }
- }
-
- /****************************************************************************/
- int /* return error number (0=no error) */
- _rstatus( /* check stream for errors */
- REC *rp, /* record pointer */
- int mode) /* mode (0=read; !0=write/append) */
- /****************************************************************************/
- {
- int errnum=0; /* error number */
- int smode; /* stream mode */
-
- /* test for valid record pointer */
- if (!risvalid(rp)) {
- errnum = rseterr(NULL, EINVAL);
- goto done;
- }
-
- /* if stream _R_WRT flag does not match mode */
- smode = rflags(rp) & _R_WRT;
- if ((mode && !smode) || (!mode && smode)) {
- errnum = rseterr(rp, R_EINVMOD);
- goto done;
- }
-
- /* if record 0 and write mode */
- if (!rrecno(rp) && mode) {
- rrecno(rp)++;
- }
-
- /* test for previous error */
- errnum = rerror(rp);
-
- done:
- return (errnum);
- }
-
- /****************************************************************************/
- static void /* returns nothing */
- _rfree( /* free the memory allocated to a record */
- REC *rp) /* record pointer */
- /****************************************************************************/
- {
- if (risvalid(rp)) {
- free(rflds(rp));
- free(rrecs(rp));
- if (rfp(rp)) fclose(rfp(rp));
- memset(rp, 0, sizeof(REC));
- }
- }
-
- /* User functions */
- /****************************************************************************/
- REC * /* return record pointer */
- ropen( /* open a record stream for reading */
- const char *fname, /* name of file to open */
- const char *mode) /* type of mode used to open file */
- /****************************************************************************/
- {
- REC *rp = _RECS; /* record pointer */
- int i; /* count of REC structures */
- int ch; /* first character of mode */
-
- /* only modes currently supported are "r", "w", and "a" */
- ch = tolower(*mode);
- if (!(ch=='r' || ch=='w' || ch=='a')) {
- rp = NULL;
- rseterr(NULL, EINVAL);
- goto done;
- }
-
- /* allocate memory for array of REC structures */
- if (!rp) {
- do {
- /* note: no memory allocation needed for recin, etc */
- rp = _RECS = (REC *) calloc(ROPEN-NREC, sizeof(REC));
- if (!rp) {
- if (rseterr(NULL, ENOMEM)) goto done;
- }
- } while (!rp);
- }
-
- /* search thru REC structures until empty position found */
- for (i=NREC+1; i <= ROPEN; i++, rp++) {
- if (!rfd(rp)) {
- rfd(rp) = i;
- break;
- }
- }
- /* error if out of positions */
- if (i > ROPEN) {
- rp = NULL;
- rseterr(NULL, EMFILE);
- goto done;
- }
-
- /* open file */
- rfp(rp) = fopen(fname, mode);
- if (!rfp(rp)) {
- rclose(rp);
- rp = NULL;
- /* if error other than path/file not found */
- if (errno != ENOENT) {
- rseterr(NULL, errno);
- }
- goto done;
- }
-
- /* initialize */
- if (ch != 'r') rflags(rp) |= _R_WRT;
- rnames(rp) = fname;
- rrecno(rp) = 0L;
- rfldno(rp) = 0;
- rcol(rp) = 0;
- rrecsiz(rp) = 0;
- rreclen(rp) = 0;
- rrecs(rp) = NULL;
- rfldsiz(rp) = 0;
- rflds(rp) = NULL;
- rfldch(rp) = RECFLDCH;
- rtxtch(rp) = RECTXTCH;
- _rsetexitfn(rp);
-
- done:
- return (rp);
- }
-
- /****************************************************************************/
- int /* return error number (0=no error) */
- rclose( /* close a record stream */
- REC *rp) /* record pointer */
- /****************************************************************************/
- {
- int errnum=0; /* error number (0=no error) */
- int i; /* count REC structures */
- REC *recp=_RECS; /* pointer to _RECS array */
-
- if (risvalid(rp)) {
- /* close record stream, but not recin, recout, recerr */
- if (rfd(rp) > NREC) _rfree(rp);
-
- /* if all record streams closed, free _RECS */
- /* note: valid rp implies valid recp */
- for (i=NREC+1; i <= ROPEN; i++, recp++) {
- if (rfd(recp)) goto done;
- }
- free(_RECS);
- _RECS = NULL;
-
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
-
- done:
- return (errnum);
- }
-
- /****************************************************************************/
- int /* returns number of streams closed */
- rcloseall( /* close all record streams */
- void) /* no arguments */
- /****************************************************************************/
- {
- int num=0; /* number of streams closed */
- int i; /* count REC structures */
- REC *recp=_RECS; /* pointer to _RECS array */
-
- /* close every open record stream, except recin, etc */
- if (recp) {
- for (i=NREC+1; i <= ROPEN; i++, recp++) {
- if (rfd(recp)) {
- _rfree(recp);
- num++;
- }
- }
- free(_RECS);
- _RECS = NULL;
- }
- return (num);
- }
-
- /****************************************************************************/
- int /* return !0 for valid; 0 for invalid */
- risvalid( /* is record pointer valid? */
- REC *rp) /* record pointer */
- /****************************************************************************/
- {
- int valid=1; /* validation state (!0=valid) */
-
- /* if rp is null pointer or rfd not between 1 and ROPEN */
- if (!rp || rfd(rp) < 1 || rfd(rp) > ROPEN) {
- /* invalid record pointer */
- valid = 0;
- }
- return (valid);
- }
-
- /****************************************************************************/
- int /* return error number (0=no error) */
- rsetfldch( /* set field separator character */
- REC *rp, /* record pointer */
- int ch) /* field separator character */
- /****************************************************************************/
- {
- int errnum=0; /* error number (0=no error) */
-
- if (risvalid(rp)) {
- if (isascii(ch)) {
- rfldch(rp) = ch;
- } else {
- errnum = rseterr(rp, R_EINVAL);
- }
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
- return (errnum);
- }
-
- /****************************************************************************/
- int /* return error number (0=no error) */
- rsettxtch( /* set text string delimiter character */
- REC *rp, /* record pointer */
- int ch) /* text delimiter character */
- /****************************************************************************/
- {
- int errnum=0; /* error number (0=no error) */
-
- if (risvalid(rp)) {
- if (isascii(ch)) {
- rtxtch(rp) = ch;
- } else {
- errnum = rseterr(rp, R_EINVAL);
- }
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
- return (errnum);
- }
-
- /****************************************************************************/
- int /* return 0 on success; errnum on error */
- rsetcxtno( /* set context number of record stream */
- REC *rp, /* record pointer */
- int cxtno) /* context number */
- /****************************************************************************/
- {
- int errnum=0; /* error number (0=no error) */
-
- if (risvalid(rp)) {
- if (rcxtno(rp) >= 0 && cxtno >= 0) {
- rcxtno(rp) = cxtno;
- } else {
- errnum = rseterr(rp, R_EINVAL);
- }
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
- return (errnum);
- }
-
- /****************************************************************************/
- int /* return 0 on success; errnum on error */
- rsetbegcolno( /* set beginning record column number */
- REC *rp, /* record pointer */
- int colno) /* first column in record is 0 or 1 */
- /****************************************************************************/
- {
- int errnum=0; /* error number (0=no error) */
-
- if (risvalid(rp)) {
- if (colno == 1) {
- rflags(rp) |= _R_COL;
- } else if (colno == 0) {
- rflags(rp) &= ~_R_COL;
- } else {
- errnum = rseterr(rp, R_EINVAL);
- }
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
- return (errnum);
- }
-